home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 4 / The 640 Meg Shareware Studio CD-ROM Volume IV (Data Express)(1994).ISO / clang / lz13.zip / LZDCMP1.ASM < prev    next >
Assembly Source File  |  1993-05-01  |  6KB  |  272 lines

  1.     title    lzdcmp - file decompressor using limpel-ziev algorithm
  2.  
  3. ;Tom Pfau
  4. ;Digital Equipment Corporation
  5. ;Parsippany, NJ
  6.  
  7. ;Constants
  8. CLEAR        equ    256
  9. EOF        equ    257
  10. FIRST_FREE    equ    258
  11. ;MAXMAX        equ    4096
  12.  
  13.     include    macros1.mlb
  14.  
  15. ;Hash table entry
  16. hash_rec    struc
  17. next    dw    ?            ; prefix code
  18. char    db    ?            ; suffix char
  19. hash_rec    ends
  20.  
  21. ;Declare segments
  22. code    segment byte public 'code'
  23. code    ends
  24. stack    segment word stack 'data'
  25.     dw    128 dup (?)
  26. stack    ends
  27. data    segment word public 'data'
  28. data    ends
  29. memory    segment para public 'memory'
  30. hash    label    hash_rec
  31. memory    ends
  32.  
  33. ;Start coding
  34. code    segment
  35.     assume    CS:code,DS:data,ss:stack,ES:data
  36.  
  37. start    proc    far
  38.     mov    bx,seg hash        ;End of program
  39.     mov    ax,DS            ;Beginning of program
  40.     sub    bx,ax            ;Size of program
  41.     inc    bx            ;Make sure
  42.     setmem    bx            ;Set program size
  43.     mov    bx,data            ;Address data segment
  44.     mov    ES,bx
  45.     mov    DS,bx
  46.     print    input_prompt        ;Get file names
  47.     input    input_file
  48.     print    crlf
  49.     print    output_prompt
  50.     input    output_file
  51.     print    crlf
  52.     mov    al,input_file+1        ;Terminate with nulls
  53.     xor    ah,ah
  54.     mov    si,ax
  55.     mov    input_file+2[si],ah    ;TH 0
  56.     mov    al,output_file+1
  57.     mov    si,ax
  58.     mov    output_file+2[si],ah    ;TH 0
  59.     hopen    input_file+2,0        ;Open input and output
  60.     mov    input_handle,ax
  61.     hcreat    output_file+2,0
  62.     mov    output_handle,ax
  63.     call    decompress        ;Decompress files
  64.     hclose    input_handle
  65.     hclose    output_handle
  66.     exit                ;Done
  67. start    endp
  68.  
  69. data    segment
  70. input_prompt    db    'Input file: $'
  71. output_prompt    db    'Output file: $'
  72. input_file    db    80,0,80 dup (?)
  73. output_file    db    80,0,80 dup (?)
  74. crlf        db    13,10,'$'
  75. input_handle    dw    ?
  76. output_handle    dw    ?
  77. data    ends
  78.  
  79. decompress    proc    near
  80.     malloc    768            ;Allocate space for hash table
  81.     mov    hash_seg,ax        ;Save segment address
  82.     hread    input_handle,input_buffer,1024    ;Read from input
  83. l1:    call    read_code        ;Get a code
  84.     cmp    ax,EOF            ;End of file?
  85.     jne    l2            ;no
  86.  
  87.     cmp    output_offset,0        ;Data in output buffer?
  88.     je    l1a            ;no
  89.      hwrite    output_handle,output_buffer,output_offset    ;Flush buffer
  90. l1a:    ret                ;done
  91.  
  92. l2:    cmp    ax,CLEAR        ;Clear code?
  93.     jne    l7            ;no
  94.  
  95.     call    init_tab        ;Initialize table
  96.     call    read_code        ;Read next code
  97.     mov    cur_code,ax        ;Initialize variables
  98.     mov    old_code,ax
  99.     mov    k,al
  100.     mov    fin_char,al
  101. ;    mov    al,k
  102.     call    write_char        ;Write character
  103.     jmp    l1            ;Get next code
  104.  
  105. l7:    mov    cur_code,ax        ;Save new code
  106.     mov    in_code,ax
  107.     mov    ES,hash_seg        ;Point to hash table
  108.     cmp    ax,free_code        ;Code in table? (k<w>k<w>k)
  109.     jl    l11            ;yes
  110.      mov    ax,old_code        ;get previous code
  111.      mov    cur_code,ax        ;make current
  112.      mov    al,fin_char        ;get old last char
  113.      push    ax            ;push it
  114.      inc    stack_count
  115. l11:    cmp    cur_code,255        ;Code or character?
  116.     jle    l15            ;Char
  117.  
  118.     mov    bx,cur_code        ;Convert code to address
  119.     call    index
  120.     mov    al,ES:2[bx]        ;Get suffix char
  121.     push    ax            ;push it
  122.     inc    stack_count
  123.     mov    ax,ES:[bx]        ;Get prefix code
  124.     mov    cur_code,ax        ;Save it
  125.     jmp    l11            ;Translate again
  126.  
  127. l15:
  128. ;    push    DS            ;Restore seg reg
  129. ;    pop    ES
  130.     mov    ax,DS
  131.     mov    ES,ax
  132.     mov    ax,cur_code        ;Get code
  133.     mov    fin_char,al        ;Save as final, k
  134.     mov    k,al
  135.     push    ax            ;Push it
  136.     inc    stack_count
  137.     mov    cx,stack_count        ;Pop stack
  138.     jcxz    l18            ;If anything there
  139. l17:     pop    ax
  140.      call    write_char
  141.      loop    l17
  142. l18:    mov    stack_count,cx        ;Clear count on stack
  143.     call    add_code        ;Add new code to table
  144.     mov    ax,in_code        ;Save input code
  145.     mov    old_code,ax
  146.     mov    bx,free_code        ;Hit table limit?
  147.     cmp    bx,max_code
  148.     jl    l23            ;Less means no
  149.      cmp    nbits,12        ;Still within twelve bits?
  150.      je    l23            ;no (next code should be clear)
  151.       inc    nbits            ;Increase code size
  152.       shl    max_code,1        ;Double max code
  153. l23:    jmp    l1            ;Get next code
  154. decompress    endp    
  155.  
  156. data    segment
  157. hash_seg    dw    ?
  158. cur_code    dw    ?
  159. old_code    dw    ?
  160. in_code        dw    ?
  161. free_code    dw    FIRST_FREE
  162. stack_count    dw    0
  163. nbits        dw    9
  164. max_code    dw    512
  165. fin_char    db    ?
  166. k        db    ?
  167. data    ends
  168.  
  169. read_code    proc    near
  170.     mov    ax,bit_offset        ;Get bit offset
  171.     add    ax,nbits        ;Adjust by code size
  172.     xchg    bit_offset,ax        ;Swap
  173.     mov    cx,8            ;Calculate byte offset
  174.     xor    dx,dx
  175.     div    cx
  176.     cmp    ax,1021            ;Approaching end of buffer?
  177.     jl    rd0            ;no
  178.  
  179.     push    dx            ;Save offset in byte
  180.     add    dx,nbits        ;Calculate new bit offset
  181.     mov    bit_offset,dx
  182.     mov    cx,1024            ;1k buffer
  183.     mov    bp,ax            ;save byte offset
  184.     sub    cx,ax            ;Calculate bytes left
  185. ;    add    ax,offset input_buffer    ;Point to char
  186.     mov    di,offset input_buffer    ;TH Point to beginning of buffer
  187.     add    ax,di            ;TH Point to char
  188.  
  189.     mov    si,ax
  190. ;    lea    di,input_buffer        ;Point to beginning of buffer
  191. rep    movsb                ;Move last chars down
  192.     hread    input_handle,[di],bp    ;Fill rest of buffer
  193.     xor    ax,ax            ;Clear ax
  194.     pop    dx            ;Restore offset in byte
  195. rd0:    add    ax,offset input_buffer    ;Point to char
  196.     mov    si,ax
  197.     lodsw                ;Get word
  198.     mov    bx,ax            ;Save in AX
  199.     lodsb                ;Next byte
  200.     mov    cx,dx            ;Offset in byte
  201.     jcxz    rd2            ;If zero, skip shifts
  202. rd1:     shr    al,1            ;Put code in low (code size) bits of BX
  203.      rcr    bx,1
  204.      loop    rd1
  205. rd2:    mov    ax,bx            ;put code in ax
  206.     mov    bx,nbits        ;mask off unwanted bits
  207.     sub    bx,9
  208.     shl    bx,1
  209.     and    ax,masks[bx]
  210.     ret
  211. read_code    endp
  212.  
  213. data    segment
  214. masks        dw    1ffh,3ffh,7ffh,0fffh
  215. input_buffer    db    1024 dup (?)
  216. bit_offset    dw    0
  217. data    ends
  218.  
  219. init_tab    proc    near
  220.     mov    nbits,9            ;Initialize variables
  221.     mov    max_code,512
  222.     mov    free_code,FIRST_FREE
  223.     ret
  224. init_tab    endp
  225.  
  226. write_char    proc    near
  227.     mov    di,output_offset    ;Get offset in buffer
  228.     cmp    di,1024            ;Full?
  229.     jl    wc1            ;no
  230.      push    ax            ;Save registers
  231.      push    cx
  232.      hwrite    output_handle,output_buffer,di    ;Write buffer to file
  233.      pop    cx
  234.      pop    ax
  235.      xor    di,di    ;TH        ;Point to beginning of buffer
  236.      mov    output_offset,di
  237. wc1:    lea    di,output_buffer[di]    ;Point into buffer
  238.     stosb                ;Store char
  239.     inc    output_offset        ;Increment number of chars in buffer
  240.     ret
  241. write_char    endp
  242.  
  243. data    segment
  244. output_offset    dw    0
  245. output_buffer    db    1024 dup (?)
  246. data    ends
  247.  
  248. index        proc    near
  249.     mov    bp,bx            ;bx = bx * 3 (3 byte entries)
  250.     shl    bx,1            ;bp = bx
  251.     add    bx,bp            ;bx = bx * 2 + bp
  252.     ret
  253. index        endp
  254.  
  255. add_code    proc    near
  256.     mov    bx,free_code        ;Get new code
  257.     call    index            ;convert to address
  258.     push    ES            ;point to hash table
  259.     mov    ES,hash_seg
  260.     mov    al,k            ;get suffix char
  261.     mov    ES:[bx].char,al        ;save it
  262.     mov    ax,old_code        ;get prefix code
  263.     mov    ES:[bx].next,ax        ;save it
  264.     pop    ES
  265.     inc    free_code        ;set next code
  266.     ret
  267. add_code    endp
  268.  
  269. code    ends
  270.  
  271.     end    start
  272.